Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

233
Visualizações
If an event issued on "this" bubbles up out of my component then why do we need the "composed" property on custom events?

So I have read several pieces that say if you want a custom event to traverse the shadow DOM boundary and cross into the light DOM you need to set the custom event's composed property to true. I noticed however that any events I dispatch from a web component's this. make it out of the shadowRoot component just fine, and ones that are dispatched from this.shadowRoot stay inside. So why do I need the "composed" property? Am I doing something wrong?

const internalEvent = new CustomEvent("internalEvent", {bubbles: true, cancelable: false})
const externalEvent = new CustomEvent("externalEvent", {bubbles: true, cancelable: false})

class MyComponent extends HTMLElement {
    constructor() {
        super()
        this.attachShadow({ mode: 'open' })
        this.shadowRoot.innerHTML = `
            <button id="internalButton">INTERNAL</button>
            <button id="externalButton">EXTERNAL</button>
        `
        this.internalButton = this.shadowRoot.getElementById("internalButton")
        this.externalButton = this.shadowRoot.getElementById("externalButton")
    }
    connectedCallback() {
        this.internalButton.addEventListener("click", ()=>{
            this.shadowRoot.dispatchEvent(internalEvent)
        })
        this.externalButton.addEventListener("click", ()=>{
            this.dispatchEvent(externalEvent)
        })
        this.shadowRoot.addEventListener("internalEvent", (event)=>{
            console.log("Internal event detected internally.")
        })
        this.shadowRoot.addEventListener("externalEvent", (event)=>{
            console.log("External event detected internally!")
        })
    }
}

document.addEventListener("internalEvent", ()=>console.log("Internal event detected externally!"))
document.addEventListener("externalEvent", ()=>console.log("External event detected externally."))
customElements.define('my-component', MyComponent)

edit: I'm just struggling to think of any reason where, to get a message to leave your component, you'd prefer to dispatch it within the shadowRoot and add a special property, rather than just dispatching it straight into the light DOM in the first place.

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

As others have mentioned, this is not in the shadow DOM of your component; it is the component that has this shadow DOM.

if I can just dispatch from this why would I not just do that instead of adding extra properties to my event?

It still wouldn't be able pass any possible surrounding shadowDOM boundaries (your web component may very well be a child or descendant of another web component that utilizes shadow DOM). This may be desirable or not, depending on where you want the event to be monitorable.

Also be aware that connectedCallback can be called multiple times, for example if an element is moved in the DOM; make sure to always remove any event listeners which you added in the connectedCallback in the disconnectedCallback, or even preferable, add the internal listeners in the constructor (which is guaranteed to only ever run once, and saves you the hassle of needing references to the listeners to be able to remove them).

about 4 years ago · Juan Pablo Isaza Relatório

0

'this' is the Custom Element/Web Component <my-component>,
'this' is not inside the elements shadowRoot.

So Events you dispatch from 'this', do not cross shadowDOM boundaries.

You only need composed: true when Events need to cross (aka "escape") shadowDOM –

<script>
  const EventName = "HelloFromComponent";
  customElements.define('my-component', class extends HTMLElement {
    constructor() {
      let attach = (btn, composed = false, el = this.shadowRoot.getElementById(btn)) =>
        el.onclick = () => {
          el.dispatchEvent(new CustomEvent(EventName, {
            bubbles: true,
            cancelable: false,
            composed: composed
          }))
        }
      super().attachShadow({mode: 'open'})
             .innerHTML = `<button id="one">One</button><button id="two">Two</button>`;
      attach("one", /* composed = */ false );
      attach("two", /* composed = */ true  );
    }
    listen(where) {
      where.addEventListener(EventName, (evt) => {
        console.log(where.nodeName, evt.type, evt.composed, );
      })
    }
    connectedCallback() {
      this.listen(this);
      this.listen(document);
    }
  });
</script>
<my-component></my-component>

about 4 years ago · Juan Pablo Isaza Relatório

0

It has just dawned on me that one reason (maybe The reason) would be if you wanted the event to be caught both inside AND outside of your component. Without the compose property you'd need to issue two separate events.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda